﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using MySql.Data.MySqlClient;
using System.Data;

namespace ProjectBuilder
{
    [DbTable("phpdoc_class")]
    public class Class : BaseDocObject
    {
        [DbField("name")]
        public string Name { get; set; }

        [DbField("file_id")]
        public long? FileId
        {
            get
            {
                if (File != null)
                    return File.GetDBId();
                return null;
            }
        }

        [DbField("package_id")]
        public long? PackageId { get; set; }

        [DbField("start_line")]
        public int StartLine { get; set; }

        [DbField("end_line")]
        public int EndLine { get; set; }

        [DbField("extends")]
        public string Extends { get; set; }

        [DbField("implements")]
        public string Implements { get; set; }

        [DbField("is_interface")]
        public int IsInterface { get; set; }

        [DbField("is_abstract")]
        public int IsAbstract { get; set; }

        [DbField("short_description")]
        public string ShortDescrition { get; set; }

        [DbField("description")]
        public string Description { get; set; }

        [DbField("version")]
        public string Version { get; set; }

        [DbField("copyright")]
        public string Copyright { get; set; }

        /*        
        public ClassType[] Childs { get; set; }

        public string[] Authors { get; set; }

        */
        public File File { get; set; }

        public Class(ProjectBuilder.PhpDocTypes.ClassType doc, Package package)
        {
            Name = doc.Name;
            IsInterface = doc.isInterface;
            StartLine = doc.Line;
            EndLine = doc.Endline;
            ShortDescrition = doc.ShortDescrition;
            Description = doc.Descrition;
            Version = doc.Version;
            Copyright = doc.Copyright;
            PackageId = package.GetDBId();
            if (doc.Tags != null)
                IsAbstract = doc.Tags.FirstOrDefault(i => i.Name == "abstract") != null ? 1 : 0;
            if (doc.Path != null)
            {
                var folder = new Folder(doc.Path);
                File = new File();
                File.Folder = folder;
                var parts = doc.Path.Split('/');
                File.Name = parts.Last<string>();
                File.Source = "";
                if (Globals.Project.SourceFiles.ContainsKey(doc.Path))
                    File.Source = Globals.Project.SourceFiles[doc.Path];
            }
            if (doc.ClassTree != null && doc.ClassTree.Length > 1)
                Extends = doc.ClassTree[doc.ClassTree.Length - 2].Value;
            if (doc.Interfaces != null)
            {
                string[] implements = new string[doc.Interfaces.Length];
                int i = 0;
                foreach (ProjectBuilder.PhpDocTypes.Interface intr in doc.Interfaces)
                {
                    implements[i] = intr.Value;
                    i++;
                }
                Implements = String.Join(",", implements);
            }
            if (doc.Tags != null)
            {
                foreach (ProjectBuilder.PhpDocTypes.Tag tag in doc.Tags)
                {
                    if (tag.Name == "abstract")
                        continue;

                    var tagObject = new Tag(tag);
                    var tagRefClass = new TagRefClass();
                    tagRefClass.TagId = (int)tagObject.GetDBId();
                    tagRefClass.ClassId = (int)GetDBId();
                    tagRefClass.Save();
                }
            }

            if (doc.Vars != null)
            {
                foreach (ProjectBuilder.PhpDocTypes.Var vr in doc.Vars)
                {
                    var vrObject = new Variable(vr, GetDBId());
                    if (vr.Tags != null)
                    {
                        foreach (ProjectBuilder.PhpDocTypes.Tag tag in vr.Tags)
                        {
                            if (tag.Name == "access")
                            {
                                vrObject.Access = tag.Value;
                                continue;
                            }
                            if (tag.Name == "abstract")
                            {
                                vrObject.IsAbstract = 1;
                                continue;
                            }
                            var tagObject = new Tag(tag);
                            var tagRefVar = new TagRefVariable();
                            tagRefVar.TagId = (int)tagObject.GetDBId();
                            tagRefVar.VariableId = (int)vrObject.GetDBId();
                            tagRefVar.Save();
                        }
                    }
                    vrObject.GetDBId();
                }
            }

            if (doc.Consts != null)
                doc.Consts.ForEach(i => new Const(i, GetDBId()).Save());

            if (doc.Methods != null)
            {
                foreach (ProjectBuilder.PhpDocTypes.Method mt in doc.Methods)
                {
                    var mtObject = new Method(mt, GetDBId());
                    if (mt.Tags != null)
                    {
                        foreach (ProjectBuilder.PhpDocTypes.Tag tag in mt.Tags)
                        {
                            if (tag.Name == "access")
                            {
                                mtObject.Access = tag.Value;
                                continue;
                            }
                            if (tag.Name == "abstract")
                            {
                                mtObject.IsAbstract = 1;
                                continue;
                            }
                            var tagObject = new Tag(tag);
                            var tagRefMeth = new TagRefMethod();
                            tagRefMeth.TagId = (int)tagObject.GetDBId();
                            tagRefMeth.MethodId = (int)mtObject.GetDBId();
                            tagRefMeth.Save();
                        }
                    }
                    if (mt.Params != null)
                        mt.Params.ForEach(i => new Param(i, mtObject.GetDBId()).Save());
                    mtObject.GetDBId();
                }
            }
            Save();
        }

        public void Save()
        {
            GetDBId();
        }

        public static long? getIdByName(string name)
        {
            var cmd = new MySqlCommand();
            var db = ObjectExtension.getAttribute<DbTableAttribute>(typeof(Class));
            cmd.CommandText = "SELECT `id` FROM `" + db.TableName + "` WHERE `name` = '" + name + "'";
            cmd.CommandType = CommandType.Text;
            cmd.Connection = Globals.Connection;
            var id = cmd.ExecuteScalar();
            if (id == null)
            {
                cmd = new MySqlCommand();
                cmd.CommandText = "INSERT INTO `" + db.TableName + "` (`name`,`new`,`build_id`) VALUES ('" + name + "','1','" + Globals.Project.BuildId + "')";
                cmd.CommandType = CommandType.Text;
                cmd.Connection = Globals.Connection;
                cmd.ExecuteNonQuery();
                id = cmd.LastInsertedId;
            }
            return int.Parse(id.ToString());
        }
    }
}